package com.sqsf.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
//标识当前类是一个切面类(就是被使用对应通知方法的类)
//等价于 <aop:aspect ref="myAspect">
public class MyAspect {
    //切点表达式的抽取
    //任意定义方法书写切点表达式 方法名就是当前切点表达式的id
    @Pointcut("execution(* com.sqsf.aop.*.*(..))")
    //书写方法使用注解定义通用切点表达式
    public void pointcut(){}
    //当前切面类中可以直接使用方法名进行调用pointcut()
    //如果其他切面类中想使用需要使用切面类.方法名进行调用MyAspect.pointcut()



    //通知注解
    // <aop:通知类型 method="方法" pointcut="切点表达式"/>
    //@通知类型("切点表达式)

    //前置通知注解
    @Before("pointcut()")
    //<aop:before method="before" pointcut="execution(* com.sqsf.aop.*.*(..))">
    public void before(){
        System.out.println("前置通知...");
    }

    //后置通知注解
    @After("MyAspect.pointcut()")
    //<aop:after method="after" pointcut="execution(* com.sqsf.aop.*.*(..))">
    public void after(){
        System.out.println("后置通知");
    }

    //环绕通知注解
    //<aop:around method="around" pointcut="execution(* com.sqsf.aop.*.*(..))">
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知");
        Object[] args = joinPoint.getArgs();
        Object proceed = joinPoint.proceed(args);
        System.out.println("环绕通知");
        return proceed;
    }

    //异常通知注解
    @AfterThrowing(value = "pointcut()",throwing = "e")
    //<aop:after-throwing method="afterThrowing" pointcut="execution(* com.sqsf.aop.*.*(..))" throwing="e">
    public void afterThrowing(Exception e){
        System.out.println("异常通知");
    }

    //返回通知注解
    @AfterReturning(value = "pointcut()",returning = "res")
    //<aop:after-returning method="afterReturning" returning="res">
    public void afterReturning(Object res){
        System.out.println("返回通知");
    }

}
